package flyweight

import (
	"fmt"
	"sync"
)

type ImageFlyweight struct {
	data string
}

func (i *ImageFlyweight) Data() string {
	return i.data
}

func NewImageFlyweight(fileName string) *ImageFlyweight {
	return &ImageFlyweight{"image:" + fileName}
}

type ImageFlyweightFactory struct {
	maps map[string]*ImageFlyweight
}

func (f *ImageFlyweightFactory) Get(fileName string) *ImageFlyweight {
	image := f.maps[fileName]
	if image == nil { // different with singleton, it will expand.
		image = NewImageFlyweight(fileName)
		f.maps[fileName] = image
	}
	return image
}

var imageFactory *ImageFlyweightFactory // global share
var once sync.Once

func GetImageFlyweightFactory() *ImageFlyweightFactory {
	once.Do(func() {
		imageFactory = &ImageFlyweightFactory{maps: make(map[string]*ImageFlyweight)}
	})
	return imageFactory
}

type ImageViewer struct {
	*ImageFlyweight
}

func (i *ImageViewer) Display() {
	fmt.Printf("show %v", i.Data())
}

func NewImageViewer(fileName string) *ImageViewer {
	imageFlyweight := GetImageFlyweightFactory().Get(fileName)
	return &ImageViewer{
		ImageFlyweight: imageFlyweight,
	}
}
